#pragma once

#include<cstdlib>
#include<utility>
#include<algorithm>
#include <iostream>
#include"Graph.h"
#include"WeighGraph.h"

namespace {
	enum datasize{SMALL, LARGE};
	int getRandomPositiveNumber(){
		return std::max<int>(rand()*(rand() / 10), 1);
	}

	Edge getRandomEdge(int vertexNum){
		int fromVertex = getRandomPositiveNumber() % vertexNum;
		int toVertex = getRandomPositiveNumber() % vertexNum;
		return{ fromVertex, toVertex };
	}
	WeighEdge getRandomWeighEdge(int vertexNum){
		int fromVertex = getRandomPositiveNumber() % vertexNum;
		int toVertex = getRandomPositiveNumber() % vertexNum;
		int weight = getRandomPositiveNumber();
		return{ fromVertex, toVertex, weight };

	}

	int getRandomNumberOnSegment(int leftBorder, int rightBorder){
		return leftBorder + (getRandomPositiveNumber()) % (rightBorder - leftBorder);
	}

	std::pair<int, int> getRandomIndexes(int vertexNum){
		int fromIndex = getRandomPositiveNumber() % (vertexNum - 1);
		int toIndex = getRandomNumberOnSegment(fromIndex + 1, vertexNum);
		return{ fromIndex, toIndex };
	}

	void generateScriptForGraph(int& vertexNum, std::vector<Edge>& egdesList){
		vertexNum = std::max<int>(5, getRandomPositiveNumber() % 100);
			
		int edgesNum = std::max<int>(getRandomPositiveNumber() % 1500, std::min<int>(vertexNum * 15, vertexNum*(vertexNum - 1) / 2));
		for (int i = 0; i < edgesNum; ++i){
			egdesList.push_back(getRandomEdge(vertexNum));
		}
	}

	void generateScriptForWeighGraph(int &vertexNum, std::vector<WeighEdge> & edgesList, datasize mode = SMALL){
		if (mode == SMALL)
			vertexNum = std::max<int>(5, getRandomPositiveNumber() % 200);
		else
			vertexNum = std::max<int>(5, getRandomPositiveNumber() % 20000);
		int edgesNum = std::max<int>(getRandomPositiveNumber() % 1500, std::min<int>(vertexNum * 20, vertexNum*(vertexNum - 1) / 2));
		for (int i = 0; i < edgesNum; ++i){
			edgesList.push_back(getRandomWeighEdge(vertexNum));
		}
	}
	std::unique_ptr<Graph> generateGraph(){
		int vertexNum;
		std::vector<Edge> edgesList;
		generateScriptForGraph(vertexNum, edgesList);

		return readGraph(vertexNum, edgesList);
	}
	int generateNumberMod(int mod){
		return getRandomPositiveNumber() % mod;
	}

	std::vector<int> generateCycle(int vertexNum){
		int lengthOfCycle = std::min<int>(vertexNum, std::max<int>(getRandomPositiveNumber() % vertexNum, 1));
		std::vector<int> vertexesInCycle(lengthOfCycle);
		for (int currentVertex = 0; currentVertex < lengthOfCycle; ++currentVertex){
			vertexesInCycle[currentVertex] = generateNumberMod(vertexNum);
		}
		return vertexesInCycle;
	}

	std::pair<int, int> getRandomNumbers(int mod){
		return{ generateNumberMod(mod), generateNumberMod(mod) };
	}

}



